package com.example.java_gobang.game;

import com.example.java_gobang.model.User;
import com.example.java_gobang.service.RoomService;
import com.example.java_gobang.tools.MatchResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Lenovo
 * Date: 2022-08-16
 * Time: 10:43
 */

//通过这个类实现匹配功能
@Component
public class Matcher {
    private Queue<User> normalQueue = new LinkedList<>();//低于 2000 分
    private Queue<User> highQueue = new LinkedList<>();
    private Queue<User> veryHighQueue = new LinkedList<>();

    @Autowired
    private OnlineUserManager onlineUserManager;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RoomService roomService;

    //操作匹配队列的方法
    public void add(User user){

        if(user.getScore() < 2000){
            synchronized (normalQueue){
                normalQueue.offer(user);
                normalQueue.notify();
            }
            System.out.println("把玩家" + user.getUsername() + "加入到 normalQueue");
        }else if(user.getScore() >= 2000 && user.getScore() < 3000){
            synchronized (highQueue){
                highQueue.offer(user);
                highQueue.notify();
            }
            System.out.println("把玩家" + user.getUsername() + "加入到 highQueue");
        }else{
            synchronized (veryHighQueue){
                veryHighQueue.offer(user);
                veryHighQueue.notify();
            }
            System.out.println("把玩家" + user.getUsername() + "加入到 veryHighQueue");
        }
    }

    //删除用户
    public void remove(User user){
        if(user.getScore() < 2000){
            synchronized (normalQueue){
                normalQueue.remove(user);
            }
            System.out.println("把玩家" + user.getUsername() + "退出 normalQueue");
        }else if(user.getScore() >= 2000 && user.getScore() < 3000){
            synchronized (highQueue){
                highQueue.remove(user);
            }
            System.out.println("把玩家" + user.getUsername() + "退出 highQueue");
        }else{
            synchronized (veryHighQueue){
                veryHighQueue.remove(user);
            }

            System.out.println("把玩家" + user.getUsername() + "退出 veryHighQueue");
        }
    }

    //创建线程扫描线程
    public Matcher(){
        Thread t1 = new Thread(){
            @SneakyThrows
            @Override
            public void run() {
                //扫描 normalQueue
                while (true){
                    handlerMatch(normalQueue);
                }
            }
        };

        t1.start();

        Thread t2 = new Thread(){
            @SneakyThrows
            @Override
            public void run() {
                while (true){
                    handlerMatch(highQueue);
                }
            }
        };

        t2.start();

        Thread t3 = new Thread(){
            @SneakyThrows
            @Override
            public void run() {
                while (true){
                    handlerMatch(veryHighQueue);
                }
            }
        };

        t3.start();
    }

    private void handlerMatch(Queue<User> matchQueue) throws IOException, InterruptedException {
        //队列里没有两个人 直接退出本轮扫描
        synchronized (matchQueue){
            while (matchQueue.size() < 2){
                matchQueue.wait();
            }

            //取出两个玩家
            User player1 = matchQueue.poll();
            User player2 = matchQueue.poll();

            System.out.println("匹配出两个玩家" + player1.getUsername() + player2.getUsername());

            //获取到玩家的 websocket 会话 为了告诉玩家你排到了
            WebSocketSession session1 = onlineUserManager.getFromGameHall(player1.getUserId());
            WebSocketSession session2 = onlineUserManager.getFromGameHall(player2.getUserId());

            //理论上匹配队列中的玩家一定是在线的
            if(session1 == null){
                //把玩家 2 重新放回匹配队列
                matchQueue.offer(player2);
                return;
            }

            //如果玩家 2 下线了 把 1 重新放回去
            if(session2 == null){
                matchQueue.offer(player1);
                return;
            }

            //排到的是一个人 但是理论上是不存在的 双开被禁止了 双重判定
            if(session1 == session2){
                //把其中的一个玩家放到匹配队列中
                matchQueue.offer(player1);
                return;
            }

            //把玩家放到一个房间里
            Room room = new Room();
            roomService.add(room,player1.getUserId(),player2.getUserId());

            //通过 websocket 返回一个 message 为 匹配成功 信息

            MatchResponse response1 = new MatchResponse();
            response1.setOk(true);
            response1.setMessage("MatchSuccess");

            session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response1)));

            MatchResponse response2 = new MatchResponse();
            response2.setOk(true);
            response2.setMessage("MatchSuccess");

            session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(response2)));
        }
    }
}
